using MicroMsg.Common.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
namespace MicroMsg.UI.UserContrl
{
	public class MMListBox : ItemsControl
	{
		public delegate void OnListFarFromBottom(bool bool_0);
		private const string TAG = "MMListBox";
		public const int cNLockFromBottomDistance = 801;
		private UIActionService mActionService;
		private ScrollViewer _scrollViewer;
		private ItemContainerGenerator _generator;
		public static DependencyProperty mListBoxKindProperty = DependencyProperty.Register("mListBoxKind", typeof(MMListBoxKind), typeof(MMListBox), new PropertyMetadata(MMListBoxKind.Kind_Default));
		public static MMListBox.OnListFarFromBottom onListFarFromBottom;
		public static readonly DependencyProperty ItemContainerStyleProperty = DependencyProperty.Register("ItemContainerStyle", typeof(Style), typeof(MMListBox), new PropertyMetadata(null));
		public bool IsAutoToBottom;
		public bool IsLockWhenFarFromBottom;
		private bool isLock;
		private double oldOffset;
		private double oldExtentHeight;
		private int ItemCountToAdd;
		private bool isBind;
		private DispatcherTimer LockTimer;
		private static readonly DependencyProperty ScrollVerticalOffsetProperty = DependencyProperty.Register("ScrollVerticalOffset", typeof(double), typeof(MMListBox), new PropertyMetadata(-1.0, new PropertyChangedCallback(MMListBox.OnScrollVerticalOffsetChanged)));
		private static readonly DependencyProperty ScrollExtentHeightProperty = DependencyProperty.Register("ScrollExtentHeight", typeof(double), typeof(MMListBox), new PropertyMetadata(-1.0, new PropertyChangedCallback(MMListBox.OnScrollExtentHeightChanged)));
		private static readonly DependencyProperty ScrollScrollableHeightProperty = DependencyProperty.Register("ScrollScrollableHeight", typeof(double), typeof(MMListBox), new PropertyMetadata(-1.0, new PropertyChangedCallback(MMListBox.OnScrollScrollableHeightChanged)));
		private static readonly DependencyProperty ScrollViewportHeightProperty = DependencyProperty.Register("ScrollViewportHeight", typeof(double), typeof(MMListBox), new PropertyMetadata(-1.0, new PropertyChangedCallback(MMListBox.OnScrollViewportHeightChanged)));
		public static readonly DependencyProperty GoDownOffsetProperty = DependencyProperty.Register("GoDownOffset", typeof(double), typeof(MMListBox), new PropertyMetadata(new PropertyChangedCallback(MMListBox.GoDownOffsetOnChanged)));
		private double targetScrollOffset = double.NaN;
		private bool visualTreeCreated;
		private FrameworkElement stackPanel;
		private VisualStateGroup scrollViewerVisualStateGroup;
		private List<MMListBoxItem> visibleItems;
		private List<MMListBoxItem> invisibleItems;
		private bool visibleItemsComputed;
		public bool IsSessionListBox;
		public event MMUIEvent mLinked;
		public event MMUIEvent mUnLinked;
		public event RoutedEventHandler LoadedComplete;
		public MMListBoxKind mListBoxKind
		{
			get
			{
				return (MMListBoxKind)base.GetValue(MMListBox.mListBoxKindProperty);
			}
			set
			{
				base.SetValue(MMListBox.mListBoxKindProperty, value);
			}
		}
		public Style ItemContainerStyle
		{
			get
			{
				return (Style)base.GetValue(MMListBox.ItemContainerStyleProperty);
			}
			set
			{
				base.SetValue(MMListBox.ItemContainerStyleProperty, value);
			}
		}
		public double GoDownOffset
		{
			get
			{
				return (double)base.GetValue(ScrollViewer.VerticalOffsetProperty);
			}
			set
			{
				this._scrollViewer.ScrollToVerticalOffset(value);
			}
		}
		public MMListBox()
		{
			this.mActionService = new UIActionService(this);
			this.mActionService.LoadedComplete += new RoutedEventHandler(this.mActionService_LoadedComplete);
			base.add_ManipulationStarted(new EventHandler<ManipulationStartedEventArgs>(this.MMListBox_ManipulationStarted));
		}
		private void MMListBox_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
		{
		}
		private void AdjustClickBug()
		{
			try
			{
				if (this._scrollViewer != null)
				{
					this._scrollViewer.ScrollToVerticalOffset(this._scrollViewer.get_VerticalOffset());
				}
			}
			catch (Exception)
			{
			}
		}
		private void MMListBox_Loaded(object sender, RoutedEventArgs e)
		{
			this.OnListChangesComplete();
		}
		public override void OnApplyTemplate()
		{
			this._scrollViewer = null;
			this._generator = null;
			this.visualTreeCreated = false;
			base.OnApplyTemplate();
			this._scrollViewer = MMListBox.FindFirstChildOfType<ScrollViewer>(this);
			if (this._scrollViewer == null)
			{
				throw new NotSupportedException("Control Template must include a ScrollViewer (wrapping ItemsHost).");
			}
			this._generator = base.get_ItemContainerGenerator();
			this.Bind();
		}
		protected override bool IsItemItsOwnContainerOverride(object item)
		{
			return item is MMListBoxItem;
		}
		private static T FindFirstChildOfType<T>(DependencyObject root) where T : class
		{
			Queue<DependencyObject> queue = new Queue<DependencyObject>();
			queue.Enqueue(root);
			while (0 < queue.get_Count())
			{
				DependencyObject dependencyObject = queue.Dequeue();
				int num = VisualTreeHelper.GetChildrenCount(dependencyObject) - 1;
				while (0 <= num)
				{
					DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, num);
					T t = child as T;
					if (t != null)
					{
						return t;
					}
					queue.Enqueue(child);
					num--;
				}
			}
			return default(T);
		}
		public void RefreshAllItems<T>() where T : DependencyObject
		{
			if (base.get_Items() == null)
			{
				return;
			}
			if (base.get_Items().get_Count() <= 0)
			{
				return;
			}
			for (int i = 0; i < base.get_Items().get_Count(); i++)
			{
				this.Refresh<T>(i);
			}
		}
		public void Refresh<T>(int index) where T : DependencyObject
		{
			if (this._generator == null)
			{
				return;
			}
			this._generator.ContainerFromIndex(index);
			MMListBoxItem mMListBoxItem = (MMListBoxItem)this._generator.ContainerFromIndex(index);
			if (mMListBoxItem == null)
			{
				return;
			}
			T t = MMListBox.FindFirstChildOfType<T>(mMListBoxItem);
			if (t == null)
			{
				return;
			}
			MMItemCtrl mMItemCtrl = t as MMItemCtrl;
			if (mMItemCtrl == null)
			{
				return;
			}
			mMItemCtrl.Refresh();
		}
		protected override void ClearContainerForItemOverride(DependencyObject element, object item)
		{
			if (this.mUnLinked != null)
			{
				MMListBoxItem mMListBoxItem = element as MMListBoxItem;
				if (mMListBoxItem == null)
				{
					return;
				}
				this.mUnLinked(this, new MMListBoxLinkEventArg(mMListBoxItem, item));
			}
			base.ClearContainerForItemOverride(element, item);
		}
		protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
		{
			base.PrepareContainerForItemOverride(element, item);
			if (this.mLinked == null)
			{
				return;
			}
			MMListBoxItem mMListBoxItem = element as MMListBoxItem;
			if (mMListBoxItem == null)
			{
				return;
			}
			this.mLinked(this, new MMListBoxLinkEventArg(mMListBoxItem, item));
		}
		public T getItemAt<T>(int index) where T : DependencyObject
		{
			if (index < 0 || index >= base.get_Items().get_Count())
			{
				return default(T);
			}
			if (this._generator == null)
			{
				return default(T);
			}
			this._generator.ContainerFromIndex(index);
			MMListBoxItem mMListBoxItem = (MMListBoxItem)this._generator.ContainerFromIndex(index);
			if (mMListBoxItem == null)
			{
				return default(T);
			}
			T t = MMListBox.FindFirstChildOfType<T>(mMListBoxItem);
			if (t == null)
			{
				return default(T);
			}
			return t;
		}
		public void PushAction(UIAction action)
		{
			this.mActionService.Push(action);
		}
		public void PushLoadAction(UILoadAction action)
		{
			this.mActionService.PushLoadAction(action);
		}
		private void mActionService_LoadedComplete(object sender, RoutedEventArgs e)
		{
			if (this.LoadedComplete != null)
			{
				this.LoadedComplete.Invoke(sender, e);
			}
		}
		public static List<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
		{
			List<T> list = new List<T>();
			if (depObj != null)
			{
				for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
				{
					DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
					if (child != null && child is T)
					{
						list.Add((T)((object)child));
					}
					List<T> list2 = MMListBox.FindVisualChildren<T>(child);
					if (list2 != null && list2.get_Count() > 0)
					{
						using (List<T>.Enumerator enumerator = list2.GetEnumerator())
						{
							while (enumerator.MoveNext())
							{
								T current = enumerator.get_Current();
								list.Add(current);
							}
						}
					}
				}
			}
			return list;
		}
		public ScrollViewer getScrollViewer()
		{
			return this._scrollViewer;
		}
		public void ScrollToLast()
		{
			this.IsAutoToBottom = true;
			if (this._scrollViewer == null)
			{
				return;
			}
			this._scrollViewer.ScrollToVerticalOffset(this._scrollViewer.get_ExtentHeight() - this._scrollViewer.get_ViewportHeight());
		}
		public void ScrollToLastWithAnimation()
		{
			TimeSpan timeSpan = TimeSpan.FromSeconds(0.3);
			Storyboard storyboard = new Storyboard();
			DoubleAnimation doubleAnimation = new DoubleAnimation();
			doubleAnimation.set_From(new double?(this._scrollViewer.get_VerticalOffset()));
			doubleAnimation.set_To(new double?(this._scrollViewer.get_ExtentHeight() - this._scrollViewer.get_ViewportHeight()));
			doubleAnimation.set_Duration(timeSpan);
			DoubleAnimation doubleAnimation2 = doubleAnimation;
			Storyboard.SetTarget(doubleAnimation2, this);
			Storyboard.SetTargetProperty(doubleAnimation2, new PropertyPath(MMListBox.GoDownOffsetProperty));
			storyboard.get_Children().Add(doubleAnimation2);
			storyboard.Begin();
		}
		public void LockScroll(int count)
		{
			if (this.isLock)
			{
				return;
			}
			if (this._scrollViewer == null)
			{
				return;
			}
			this.isLock = true;
			this.ItemCountToAdd = count;
			Log.smethod_5("MMListBox", "LockScroll ItemCountToAdd =" + this.ItemCountToAdd);
			this.SaveLocation();
		}
		private void SaveLocation()
		{
			this.oldOffset = this._scrollViewer.get_VerticalOffset();
			this.oldExtentHeight = this._scrollViewer.get_ExtentHeight();
		}
		public void UnLockScroll()
		{
			if (!this.isLock)
			{
				return;
			}
			this.ItemCountToAdd = 0;
			this.isLock = false;
		}
		public bool IsLock()
		{
			return this.isLock;
		}
		private void Bind()
		{
			if (this.isBind)
			{
				return;
			}
			if (this._scrollViewer == null)
			{
				return;
			}
			DependencyProperty arg_41_1 = MMListBox.ScrollVerticalOffsetProperty;
			Binding binding = new Binding();
			binding.set_Source(this._scrollViewer);
			binding.set_Path(new PropertyPath("VerticalOffset", new object[0]));
			base.SetBinding(arg_41_1, binding);
			DependencyProperty arg_76_1 = MMListBox.ScrollExtentHeightProperty;
			Binding binding2 = new Binding();
			binding2.set_Source(this._scrollViewer);
			binding2.set_Path(new PropertyPath("ExtentHeight", new object[0]));
			base.SetBinding(arg_76_1, binding2);
			DependencyProperty arg_AB_1 = MMListBox.ScrollScrollableHeightProperty;
			Binding binding3 = new Binding();
			binding3.set_Source(this._scrollViewer);
			binding3.set_Path(new PropertyPath("ScrollableHeight", new object[0]));
			base.SetBinding(arg_AB_1, binding3);
			DependencyProperty arg_E0_1 = MMListBox.ScrollViewportHeightProperty;
			Binding binding4 = new Binding();
			binding4.set_Source(this._scrollViewer);
			binding4.set_Path(new PropertyPath("ViewportHeight", new object[0]));
			base.SetBinding(arg_E0_1, binding4);
			this.LockTimer = new DispatcherTimer();
			this.LockTimer.add_Tick(new EventHandler(this.LockTimer_Tick));
			this.LockTimer.set_Interval(new TimeSpan(0, 0, 0, 1));
			this.isBind = true;
		}
		private void LockTimer_Tick(object sender, EventArgs e)
		{
			Log.smethod_5("MMListBox", "UnLockScroll in timer");
			this.UnLockScroll();
			DispatcherTimer dispatcherTimer = sender as DispatcherTimer;
			if (dispatcherTimer == null)
			{
				return;
			}
			dispatcherTimer.Stop();
		}
		private static void OnScrollVerticalOffsetChanged(DependencyObject dependencyObject_0, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs_0)
		{
		}
		private static void OnScrollExtentHeightChanged(DependencyObject dependencyObject_0, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs_0)
		{
			MMListBox mMListBox = dependencyObject_0 as MMListBox;
			if (mMListBox == null)
			{
				return;
			}
			if (mMListBox._scrollViewer == null)
			{
				return;
			}
			if (mMListBox.IsLock())
			{
				double num = mMListBox._scrollViewer.get_VerticalOffset() + (double)dependencyPropertyChangedEventArgs_0.get_NewValue() - (double)dependencyPropertyChangedEventArgs_0.get_OldValue();
				if (num < 0.0)
				{
					num = 0.0;
				}
				mMListBox._scrollViewer.ScrollToVerticalOffset(num);
				mMListBox.ItemCountToAdd--;
				if (mMListBox.ItemCountToAdd <= 0)
				{
					Log.smethod_5("MMListBox", "list.UnLockScroll();");
					mMListBox.UnLockScroll();
					if (mMListBox.LockTimer != null)
					{
						mMListBox.LockTimer.Stop();
						return;
					}
				}
				else
				{
					if (mMListBox.LockTimer != null)
					{
						mMListBox.LockTimer.Stop();
						mMListBox.LockTimer.Start();
						return;
					}
				}
			}
			else
			{
				if ((double)dependencyPropertyChangedEventArgs_0.get_NewValue() < (double)dependencyPropertyChangedEventArgs_0.get_OldValue())
				{
					return;
				}
				if (mMListBox.IsAutoToBottom)
				{
					if (mMListBox.IsLockWhenFarFromBottom && mMListBox.isFarFromBottom())
					{
						if (MMListBox.onListFarFromBottom != null)
						{
							MMListBox.onListFarFromBottom(true);
						}
						return;
					}
					if (mMListBox != null)
					{
						mMListBox._scrollViewer.ScrollToVerticalOffset(mMListBox._scrollViewer.get_ExtentHeight() - mMListBox._scrollViewer.get_ViewportHeight());
					}
					if (MMListBox.onListFarFromBottom != null)
					{
						MMListBox.onListFarFromBottom(false);
					}
				}
			}
		}
		public bool isFarFromBottom()
		{
			bool result = false;
			if (this._scrollViewer != null)
			{
				result = (this._scrollViewer.get_VerticalOffset() < this._scrollViewer.get_ExtentHeight() - this._scrollViewer.get_ViewportHeight() - 801.0);
			}
			return result;
		}
		private static void OnScrollScrollableHeightChanged(DependencyObject dependencyObject_0, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs_0)
		{
		}
		private static void OnScrollViewportHeightChanged(DependencyObject dependencyObject_0, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs_0)
		{
			MMListBox mMListBox = dependencyObject_0 as MMListBox;
			if (mMListBox == null)
			{
				return;
			}
			if (mMListBox._scrollViewer == null)
			{
				return;
			}
			if (!mMListBox.IsLock() && mMListBox.IsAutoToBottom)
			{
				mMListBox._scrollViewer.ScrollToVerticalOffset(mMListBox._scrollViewer.get_ExtentHeight() - mMListBox._scrollViewer.get_ViewportHeight());
			}
		}
		private static void GoDownOffsetOnChanged(DependencyObject dependencyObject_0, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs_0)
		{
			((MMListBox)dependencyObject_0).GoDownOffset = (double)dependencyPropertyChangedEventArgs_0.get_NewValue();
		}
		protected override DependencyObject GetContainerForItemOverride()
		{
			MMListBoxItem mMListBoxItem = new MMListBoxItem();
			mMListBoxItem.Owner = this;
			if (this.ItemContainerStyle != null)
			{
				mMListBoxItem.set_Style(this.ItemContainerStyle);
			}
			return mMListBoxItem;
		}
		internal List<MMListBoxItem> GetVisibleItemsAsMutableList()
		{
			if (!this.visibleItemsComputed)
			{
				this.ComputeVisibleItems();
			}
			return this.visibleItems;
		}
		protected override Size ArrangeOverride(Size finalSize)
		{
			Size result = base.ArrangeOverride(finalSize);
			this.CompleteVisualSetup();
			this.OnListChangesComplete();
			if (!double.IsNaN(this.targetScrollOffset))
			{
				this.targetScrollOffset = double.NaN;
			}
			return result;
		}
		private void CompleteVisualSetup()
		{
			if (this.visualTreeCreated)
			{
				return;
			}
			this.HookScrollingEvents();
			this.stackPanel = Enumerable.FirstOrDefault<FrameworkElement>(this._scrollViewer.GetVisualDescendents(true));
			if (this.stackPanel == null)
			{
				throw new InvalidOperationException("LazyListBox can only be used with a virtualized list; are you missing an ItemTemplate?");
			}
			this.visualTreeCreated = true;
		}
		private void HookScrollingEvents()
		{
			FrameworkElement frameworkElement = null;
			try
			{
				frameworkElement = this._scrollViewer.GetVisualChild(0);
			}
			catch
			{
			}
			if (frameworkElement == null)
			{
				return;
			}
			this.scrollViewerVisualStateGroup = frameworkElement.GetVisualStateGroup("ScrollStates");
			if (this.scrollViewerVisualStateGroup != null)
			{
				this.scrollViewerVisualStateGroup.add_CurrentStateChanging(new EventHandler<VisualStateChangedEventArgs>(this.ScrollingStateChanging));
			}
		}
		private void ScrollingStateChanging(object sender, VisualStateChangedEventArgs e)
		{
			this.OnListChangesComplete();
			if ("NotScrolling" == e.get_NewState().get_Name())
			{
				this.AdjustClickBug();
			}
		}
		public void ForceComputeVisible()
		{
			this.OnListChangesComplete();
		}
		private void OnListChangesComplete()
		{
			this.ComputeVisibleItems();
			if (this.visibleItems.get_Count() == 0 && this.invisibleItems.get_Count() > 0)
			{
				return;
			}
			using (List<MMListBoxItem>.Enumerator enumerator = this.visibleItems.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					MMListBoxItem current = enumerator.get_Current();
					current.SetIsVisible(true, 0);
					this.OnItemVisible(current);
				}
			}
			using (List<MMListBoxItem>.Enumerator enumerator2 = this.invisibleItems.GetEnumerator())
			{
				while (enumerator2.MoveNext())
				{
					MMListBoxItem current2 = enumerator2.get_Current();
					current2.SetIsVisible(false, 0);
				}
			}
			this.visibleItemsComputed = true;
		}
		public void OnItemVisible(MMListBoxItem item)
		{
			switch (this.mListBoxKind)
			{
			case MMListBoxKind.Kind_Default:
				return;
			case MMListBoxKind.Kind_SessionList:
			{
				SessionListItem sessionListItem = MMListBox.FindFirstChildOfType<SessionListItem>(item);
				if (sessionListItem == null)
				{
					return;
				}
				sessionListItem.SetVisible();
				return;
			}
			case MMListBoxKind.Kind_Timeline:
			{
				TimelineItemContainer timelineItemContainer = MMListBox.FindFirstChildOfType<TimelineItemContainer>(item);
				if (timelineItemContainer == null)
				{
					return;
				}
				timelineItemContainer.OnVisible();
				return;
			}
			}
		}
		private void ComputeVisibleItems()
		{
			List<MMListBoxItem> list = null;
			List<MMListBoxItem> list2 = null;
			List<MMListBoxItem> list3 = null;
			if (this._scrollViewer == null)
			{
				return;
			}
			this.stackPanel.GetVisualDescendents(true).GetVisibleItems(this._scrollViewer, 0, out list, out list2, out list3);
			this.visibleItems = list2;
			this.invisibleItems = Enumerable.ToList<MMListBoxItem>(Enumerable.Concat<MMListBoxItem>(list, list3));
		}
	}
}
